//
//  CoinRankListReactir.swift
//  RxStudy
//
//  Created by TRS-Mobile on 2022/11/3.
//  Copyright © 2022 season. All rights reserved.
//

import Foundation
import ReactorKit
import RxSwift

class CoinRankListReactor: Reactor {
    
    enum Action {
        case refresh
        case loadMore
    }
    
    enum Mutation {
        case setPage(Int)
        case refreshData([CoinRank])
        case addData([CoinRank])
        case setRefreshState(MJRefreshAction)
    }
    
    struct State {
        var currentPage: Int = 1;
        var dataSource: [CoinRank] = []
        var refreshState: MJRefreshAction = .begainRefresh
    }
    
    var initialState: State = State()
    
    func mutate(action: Action) -> Observable<Mutation> {
        switch action {
            
        case .refresh:
            let begin = Observable.just(Mutation.setRefreshState(.begainRefresh))
            let page = Observable.just(Mutation.setPage(1))
            
            let request = requestData(page: currentState.currentPage)
            
            let r = request
                .compactMap {$0.datas}
                .map {Mutation.refreshData($0)}
            
            let load = request
                .map {$0.isNoMoreData}
                .map {Mutation.setRefreshState($0 ? .showNomoreData : .stopRefresh)}
            
            return Observable.concat(begin, page, r, load)
        case .loadMore:
            
            let begin = Observable.just(Mutation.setRefreshState(.begainLoadmore))
            
            let page = Observable
                .just(Mutation.setPage(currentState.currentPage + 1))
            
            let request = requestData(page: currentState.currentPage)
            
            let add = request
                .compactMap {$0.datas}
                .map {Mutation.addData($0)}
            
            let load = request
                .map {$0.isNoMoreData}
                .map {Mutation.setRefreshState($0 ? .showNomoreData : .stopLoadmore)}
            
            return Observable.concat(begin, page, add, load)
        }
    }
    
    func reduce(state: State, mutation: Mutation) -> State {
        var state = state
        switch mutation {
        case .setPage(let page):
            state.currentPage = page
        case .refreshData(let data):
            state.dataSource = data
        case .addData(let data):
            state.dataSource += data
        case .setRefreshState(let rstate):
            state.refreshState = rstate
        }
        return state
    }
    
    func requestData(page: Int) -> Observable<Page<CoinRank>> {
        return myProvider.rx
            .request(MyService.coinRank(currentState.currentPage))
            .map(BaseModel<Page<CoinRank>>.self)
            .map {$0.data}
            .compactMap { $0 }
            .asObservable()
            .share(replay: 1)
    }
}
